package com.pan.service.impl;

import com.pan.dao.coupon.CouponSelectDao;
import com.pan.dao.couponHistory.CouponHistoryDao;
import com.pan.dao.couponHistory.CouponHistorySelectDao;
import com.pan.dao.couponHistory.CouponHistoryUpdateDao;
import com.pan.dao.couponRelationCategory.CouponRelationCategoryDao;
import com.pan.dao.couponRelationGoods.CouponRelationGoodsDao;
import com.pan.entity.Coupon;
import com.pan.entity.CouponHistory;
import com.pan.entity.Result;
import com.pan.enume.ResultEnum;
import com.pan.excep.error.ServiceException;
import com.pan.feign.UserServerClient;
import com.pan.feign.vo.UserVo;
import com.pan.service.CouponHistoryService;
import com.pan.service.CouponService;
import com.pan.tools.ConvertObject;
import com.pan.tools.RedisTools;
import com.pan.vo.CouponShowVo;
import com.pan.vo.UserCouponShowVo;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;


@Service("couponHistoryService")
public class UserCouponServiceImpl implements CouponHistoryService {

    @Resource
    private CouponHistorySelectDao couponHistorySelectDao;

    @Resource
    private CouponRelationCategoryDao couponRelationCategoryDao;

    @Resource
    private CouponRelationGoodsDao couponRelationGoodsDao;

    @Resource
    private CouponSelectDao couponSelectDao;
    @Resource
    private RedisTools redisTools;

    @Resource
    private UserServerClient userServerClient;

    @Resource
    private CouponService couponService;

    @Resource
    private CouponHistoryDao couponHistoryDao;

    @Resource
    private CouponHistoryUpdateDao couponHistoryUpdateDao;


    @Override
    public Result<CouponShowVo> selectCouponInfo(Long couponHistoryId){
        CouponHistory couponHistory = couponHistorySelectDao.selectById(couponHistoryId);
        Optional<CouponHistory> optionalCouponHistory = Optional.ofNullable(couponHistory);
        if (!optionalCouponHistory.isPresent()){
            return new Result<>(ResultEnum.NOT_FOUND_ERROR);
        }
        Long couponId = couponHistory.getCouponId();
        Result<CouponShowVo> result =  couponService.selectShowVoById(couponId);
        return result;
    }

    @Override
    public Result<List<UserCouponShowVo>> selectByUser(String userTicket){
        Result resultUserId = redisTools.hget("user:"+userTicket,"id");
        Long userId = Long.parseLong((String)  resultUserId.getData());
        List<CouponHistory> li = couponHistorySelectDao.selectByUserId(userId);
        List<UserCouponShowVo> li_show = new ArrayList<>();
        li.forEach(i->{
            UserCouponShowVo userCouponShowVo = new UserCouponShowVo();
            Long couponId = i.getCouponId();
            Coupon coupon = couponSelectDao.selectById(couponId);
            userCouponShowVo = ConvertObject.copySameParameter(userCouponShowVo,i);
            userCouponShowVo = ConvertObject.copySameParameter(userCouponShowVo,coupon);
            userCouponShowVo.setHistoryId(i.getId());
            userCouponShowVo.setCategoryList(couponRelationCategoryDao.selectByCouponId(couponId));
            userCouponShowVo.setGoodsList(couponRelationGoodsDao.selectByCouponId(couponId));
            li_show.add(userCouponShowVo);
        });
        Result<List<UserCouponShowVo>> result = new Result<>(ResultEnum.SUCCESS,li_show);
        return result;
    }

    //下面的几个方法要通过Seate的@GlobalTransactional 保证事物一致性，现在

//    @GlobalTransactional
    @Override
    public Result receiveCoupon(String userTicket, Long couponId){
        Long userId = Long.parseLong((String) redisTools.hget("user:"+userTicket,"id").getData());
        Coupon coupon = couponSelectDao.selectById(couponId);
        if (coupon == null){
            return new Result(ResultEnum.NOT_FOUND_ERROR);
        }
        Integer publishCount = coupon.getPublishCount();
        Integer receiveCount = coupon.getReceiveCount();
        if (publishCount == receiveCount){
            return new Result(403,"该优惠券已经领取完");
        }
        if (System.currentTimeMillis() > coupon.getEndDate().getTime()){
            return new Result(403,"该优惠券已经过期");
        }
        if (System.currentTimeMillis() < coupon.getStartDate().getTime()){
            return new Result(403,"该优惠券未开始领取");
        }
        Integer userReceiveCount = couponHistoryDao.selectCountByCouponIdAndUserId(userId,couponId);
        Integer userLimit = coupon.getUserLimit();
        if (userLimit != -1 && userLimit<=userReceiveCount){
            return  new Result<>(403,"用户已经领完该优惠券");
        }
        Result<UserVo> userVoResult= userServerClient.selectById(userId);
        UserVo userVo = userVoResult.getData();
        Long balance = userVo.getScore() - new Long(coupon.getScorePrice());
        if (balance < 0){
            return new Result(403,"账户积分不足");
        }
        Result isReceive = null;
        try {
            isReceive = userServerClient.updateNoCookie(userTicket,"score",balance);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        if (isReceive.getCode()!=200){
            throw new ServiceException(500,"扣除积分失败");
        }
        CouponHistory couponHistory = new CouponHistory();
        couponHistory.setCouponId(couponId).setUserId(userId)
                .setCreateDate(new Timestamp(System.currentTimeMillis()))
                .setUseType(0).setOrderId(null).setUseDate(null);
        couponHistoryDao.insert(couponHistory);
        return new Result(ResultEnum.SUCCESS);
    }


    @Transactional
    @Override
    public Result useCoupon(String userTicket, Long id, Long orderId){
        CouponHistory couponHistory = couponHistorySelectDao.selectById(id);
        if (couponHistory == null){
            return new Result(ResultEnum.NOT_FOUND_ERROR);
        }
        Long userId = Long.parseLong( (String) redisTools.hget("user:"+userTicket,"id").getData());
        if (couponHistory.getUserId().equals(userId)){
            return new Result(403,"该优惠券不属于该用户");
        }
        Timestamp nowTime = new Timestamp(System.currentTimeMillis());
        couponHistory.setUseType(1)
                .setUseDate(nowTime)
                .setOrderId(orderId);
        couponHistoryDao.useCoupon(couponHistory);

        return new Result(ResultEnum.SUCCESS);

    }

    @Override
    public Result<Boolean> isUserCoupon(Long userId, Long couponHistoryId){
        CouponHistory couponHistory = couponHistorySelectDao.selectById(couponHistoryId);
        if (couponHistory == null){
            return new Result().setCode(403).setData("信息错误");
        }
        Result<Boolean> result = new Result(ResultEnum.SUCCESS)
                .setData(userId.equals(couponHistory.getUserId())?true:false);
        return result;
    }

}
